//============================================================================
// Name        : TP.cpp
// Author      : JMFC
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include <time.h>
#include "NGramas.h"
#include "miniGoogle.h"
#include <math.h>
#include <climits>
#include "cargadorDeArchivos.h"
#define TEST_SET "test_v2.txt"
#define COEFICIENTE_GOOGLE 0.5
#define INDICE_MAXIMO 100000 //BORRRAR ESTO Y SE CAEN TODOS LOS LIMITES,VAN A TIRAR ERROR
using namespace std;

//TODO: probada para header = "id,sentence", corroborar
FILE* abrirTestSet(){
	FILE* file = fopen(TEST_SET, "r");
	char str[20];
	fscanf(file, "%[^\n]\n", str); //LE SACO EL HEADER!
	return file;
}

//TODO: header = "id","sentence", corroborar
FILE* abrirResultado(){
	FILE* file = fopen("pepito.txt", "w");
	string header = "";
	header += '"';
	header += "id";
	header += '"';
	header += ',';
	header += '"';
	header += "sentence";
	header += '"';
	header += '\n';

	fprintf(file, header.c_str());
	return file;
}

//probada
string leerFraseDelTest(FILE* testSet, int id){
	int len = 10000;
	char str[len];
	int lenId = floor((int)log10((float)id)) + 1;
	fscanf(testSet, "%[^\n]\n", str);
	string frase = "";
	frase += str;
	frase = frase.substr( lenId + 2, frase.length() - (3 + lenId) );

	return frase;
}



string completarFrase(string fraseIncompleta,
		diccionario_t* dic,
		diccionarioPorIndice_t* dicPorIndice,
		mapaDeTrigramas_t* trigramas){


	vector<string> palabras;
	split(fraseIncompleta, ' ', &palabras);
	size_t cantidadPalabrasEnFrase = palabras.size();
	//if(cantidadPalabrasEnFrase == 0) return "Hello!"; //obvio, por educacion
	if(cantidadPalabrasEnFrase <= 2) return "Hello!"; //obvio, por educacion


	cout<<"Va a entrar a encontrarHueco \n";
	size_t iMin = encontrarHueco(&palabras, dic, dicPorIndice, trigramas);

	cout<<"Salio de encontrarHueco \n";

	vector<palabraYProbabilidad> candidatas;


	cout<<"Va a entrar a obtenerCandidatas \n";

	if (iMin <= 1){
		cout<<"iMin es menor o igual a 1, se pone iMin =2 \n";
		iMin = 2;
	}

	obtenerCandidatas(
			palabras[iMin-2], palabras[iMin-1],
			dic, dicPorIndice, trigramas,
			&candidatas);




	//logDeCompletarFrase<<"Salio de obtenerCandidatas \n";
	cout<<"Salio de obtenerCandidatas \n";

	size_t cantidadDeCandidatas = candidatas.size();
	float distancia;
	palabraYProbabilidad palabraFaltante;
	float probabilidadActual;
	palabraFaltante.probabilidad = 0; palabraFaltante.palabra = "the"; //cualquier cosa, que agregue "the"

	cout<<"Va a entrar al for de miniGoogle \n";
	if (cantidadDeCandidatas == 0){
		cout<<"La cantidad de candidatas es cero\n\n\n";
	}

	vector<string> listaDePalabras;
	split(fraseIncompleta, ' ', &listaDePalabras);
	for(size_t i = 0; i < cantidadDeCandidatas; i++){
		//distancia = (miniGoogleDistanciaPalabraFrase(candidatas[i].palabra, fraseIncompleta, dic, dicPorIndice));
		distancia = (miniGoogleDistanciaPalabraFrase(candidatas[i].palabra, &listaDePalabras, dic, dicPorIndice));
		probabilidadActual = (1- COEFICIENTE_GOOGLE)*candidatas[i].probabilidad + COEFICIENTE_GOOGLE * (1 - distancia);
		if(probabilidadActual > palabraFaltante.probabilidad){
			palabraFaltante.palabra = candidatas[i].palabra;
			palabraFaltante.probabilidad = probabilidadActual;
		}
	}
	listaDePalabras.clear();
	cout<<"Salio del for de miniGoogle \n";

	cout<<"Va a armar la frase completa \n";
	string fraseCompleta = palabras[0];

	cout<<"Va a devolver la fraseCompelta \n";


	for(size_t j = 1; j < cantidadPalabrasEnFrase ; j++){
		if(j == iMin){
			fraseCompleta += ' ';
			fraseCompleta += palabraFaltante.palabra;
		}
		fraseCompleta += ' ';
		fraseCompleta += palabras[j];
	}


	return fraseCompleta;
}

//probada!
void guardarFraseEnResultado(FILE* archivo, int id, string frase){
	fprintf(archivo, "%d,%c%s%c\n", id, '"', frase.c_str(),'"');
}











//TODO: fijate ahora si anda, que probe la leerFrase
void extraerIndices(FILE* testSet, diccionario_t* dic, set<int>* indices){

	//ofstream indicesRelevantes("indicesRelevantes.txt");

	string fraseIncompleta;
	int id = 1;

	while(!feof(testSet) && id<=INDICE_MAXIMO){
		fraseIncompleta = leerFraseDelTest(testSet, id);
		vector<string> palabrasDeFrase;
		split(fraseIncompleta, ' ', &palabrasDeFrase);
		for(auto& palabra : palabrasDeFrase)
			if(dic->mapa.find(palabra) != dic->mapa.end()){
				indices->insert(dic->mapa.at(palabra).index);
			}
		id++;
	}

	/*for (auto& indice: (*indices)){
		indicesRelevantes<<indice<<" \n";
	}


	indicesRelevantes.close();
	*/

}




int main() {
	cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!

	clock_t tStart = clock();

	diccionario_t dicAMedias;
	cargarDiccionarioAMedias(& dicAMedias);
	printf("Time taken cargarDiccionarioAMedias(): %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);
	cout<<"Size del diccionario: "<<dicAMedias.mapa.size()<<"\n";
	FILE* testSet;
	testSet = abrirTestSet();
	set<int> indicesDelTestSet;
	extraerIndices(testSet, & dicAMedias, &indicesDelTestSet);
	printf("Time taken extraerIndices(): %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);
	cout<<"Size del set: "<<indicesDelTestSet.size()<<"\n";
	dicAMedias.mapa.clear();


	diccionarioPorIndice_t dicPorIndice;
	diccionario_t dic;
	//cargarDiccionario(&dic, &dicPorIndice, &indicesDelTestSet);

	cargarPalabrasEIndicesEnDiccionarios(&dic, &dicPorIndice, &indicesDelTestSet);
	cargarAparicionesEnDiccionario(&dic, &dicPorIndice, &indicesDelTestSet);


	printf("Time taken cargarDiccionario(): %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);


	mapaDeTrigramas_t trigramas;
	cargarTrigramas(&indicesDelTestSet, &trigramas);
	printf("Time taken cargarTrigramas(): %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);


	indicesDelTestSet.clear();


	fclose(testSet);
	testSet = abrirTestSet();

	FILE* fileResultado;
	fileResultado = abrirResultado();

	string fraseIncompleta, fraseCompleta;
	int id = 1;

	printf("Time taken A partir de aca entra al while con: %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);
	while(!feof(testSet) && id <=INDICE_MAXIMO){
		cout<<"Va a leer frase \n";
		fraseIncompleta = leerFraseDelTest(testSet, id);
		cout<<"Va a entrar a completar frase \n";
		fraseCompleta = completarFrase(fraseIncompleta, &dic, & dicPorIndice, &trigramas);
		cout<<"Va a guardar frase en resultado \n";
		guardarFraseEnResultado(fileResultado, id, fraseCompleta);
		id++;
	}
	fclose(testSet);
	fclose(fileResultado);

	printf("Time taken completarFrases: %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);


	int i;
	cout<<"Ingresar un numero: ";
	cin>>i;


	return 0;




}




































































//	ifstream archivoDeApariciones("apariciones.txt");
//	ofstream aparicionesRelevantes("aparicionesRelevantes.txt");
//
//	int indiceDePalabra;
//	char listaDeApariciones[2000000];
//	int k = 1;
//	while ( archivoDeApariciones>>indiceDePalabra/* && k!=0*/){
//		archivoDeApariciones.getline(listaDeApariciones,2000000);
//
//		if (indicesDelTestSet.find(indiceDePalabra) != indicesDelTestSet.end()){
//			//cout<<indiceDePalabra<<" ";
//			//cout<<listaDeApariciones<<"\n";
//
//			//cout<<"Ingresar k: ";
//			//cin>>k;
//
//			aparicionesRelevantes<<indiceDePalabra;
//			string listaStr(listaDeApariciones);
//
//			if (listaStr.size()>1){
//				listaStr.erase(0,1);
//				aparicionesRelevantes<<listaStr<<"\n";
//			}
//		}
//	}
//
//
//
//
//	archivoDeApariciones.close();
//	aparicionesRelevantes.close();









/*	ofstream logDeMapaDeTrigramas("logDeMapaDeTrigramasCompleto.txt");
	int primerPalabra = (trigramas.begin()->first);
		map<int,map<int,int>> mapaDeBigramas = trigramas[primerPalabra];
		int segundaPalabra = (*mapaDeBigramas.begin()).first;
			map<int,int> mapaTercerPalabraFrecuencia = mapaDeBigramas[segundaPalabra];
			int terceraPalabraPrimera = (*mapaTercerPalabraFrecuencia.begin()).first;
			int frecuenciaTercerPalabraPrimera = mapaTercerPalabraFrecuencia[terceraPalabraPrimera];
			int terceraPalabraUltima = (*mapaTercerPalabraFrecuencia.rbegin()).first;
			int frecuenciaTercerPalabraUltima = mapaTercerPalabraFrecuencia[terceraPalabraUltima];
		int segundaPalabraUltima = (*mapaDeBigramas.rbegin()).first;
	int primerPalabraUltima = (*trigramas.rbegin()).first;
		map<int,map<int,int>> mapaDeBigramasUltimo = trigramas[primerPalabraUltima];
		int segundaPalabraPerimeraDeUltimaPrimerPalabra = (*mapaDeBigramasUltimo.begin()).first;
	logDeMapaDeTrigramas<<"El primer trigrama es: \n";
	logDeMapaDeTrigramas<<primerPalabra<<"\n";
	logDeMapaDeTrigramas<<segundaPalabra<<"\n";
	logDeMapaDeTrigramas<<terceraPalabraPrimera<<"\n";
	logDeMapaDeTrigramas<<frecuenciaTercerPalabraPrimera<<"\n";
	logDeMapaDeTrigramas<<terceraPalabraUltima<<"\n";
	logDeMapaDeTrigramas<<frecuenciaTercerPalabraUltima<<"\n";
	logDeMapaDeTrigramas<<segundaPalabraUltima<<"\n";
	logDeMapaDeTrigramas<<primerPalabraUltima<<"\n";
	logDeMapaDeTrigramas<<segundaPalabraPerimeraDeUltimaPrimerPalabra<<"\n";
	logDeMapaDeTrigramas.close();
*/















/*

	diccionario_t diccionario;
	diccionarioPorIndice_t diccionarioPorIndice;

	ofstream log("log.txt");

	{
		ifstream archivoDiccionario("diccionario.txt");
		int indice;
		string palabra;
		int frecuencia;
		while (archivoDiccionario>>indice && archivoDiccionario>>palabra && archivoDiccionario>>frecuencia){
			termino_t termino;
			termino.index = indice;
			termino.frecuencia = frecuencia;
			diccionario.mapa[palabra] = termino;

			diccionarioPorIndice[indice] = palabra;
		}
		archivoDiccionario.close();
	}
	cout<<diccionario.mapa["court-appointed"].index<<" "<<diccionario.mapa["court-appointed"].frecuencia<<"\n";
	printf("Time taken cargarDiccionarioAMedias(): %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);

	FILE* testSet;
	testSet = abrirTestSet();

	set<int> indicesDelTestSet;
	extraerIndices(testSet, &diccionario, &indicesDelTestSet);
	cout<<"Size del set: "<<indicesDelTestSet.size()<<"\n";
	//log<<"Size del set: "<<indicesDelTestSet.size()<<"\n";
	printf("Time taken extraerIndices(): %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);

	{
		ifstream archivoApariciones("apariciones.txt");
		int indice;
		bool seIndexanApariciones;
		int frecuencia;
		while (archivoApariciones>>indice && archivoApariciones>>seIndexanApariciones ){

			if (indicesDelTestSet.find(indice) != indicesDelTestSet.end()){

				//log<<"Entro al if con el indice: "<<indice<<"\n";

				string palabra = diccionarioPorIndice[indice];

				diccionario.mapa[palabra].sonAparicones = seIndexanApariciones;

				string fragmento;
				archivoApariciones>>fragmento;
				while (fragmento != "$"){
					diccionario.mapa[palabra].setDeFragmentos.insert(atoi(fragmento.c_str()));
					archivoApariciones>>fragmento;
				}
				//log<<"Salio del while con el fragmento: "<<fragmento<<"\n";
				log<<"Indice: "<<indice<<", tamanio del set: "<<diccionario.mapa[palabra].setDeFragmentos.size()<<"\n";

			}
			else{
				//log<<"Entro al else con el indice: "<<indice<<"\n";
				char listaDeApariciones[1218100];
				archivoApariciones.getline(listaDeApariciones,1218100);
			}
		}
		archivoApariciones.close();
	}


	printf("Time taken cargarApariciones(): %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);

	log.close();
*/
